home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / asm / Asm_Course2.lha / Teil16.TXT < prev    next >
Text File  |  1993-09-01  |  11KB  |  317 lines

  1.           A S S E M B L E R - K U R S       (c)  Jeff Kandle 1990
  2.  
  3.                                 16.Teil...
  4.  
  5. So, nachdem wir wissen wie wir unsere sachen auch weitergeben und damit
  6. Strunzen koennen, macht es doch gleich wieder spass, oder ?
  7.  
  8. In diesem Teil werde ich am anfang erstmal ein paar neue Befehle
  9. vorstellen, sie aber nicht in irgendein programm verpacken. Ich bin sicher
  10. das ihr diese Befehle irgendwann gut gebrauchen koennt, und dann erinnert
  11. ihr euch bestimmt daran.
  12.  
  13. Als ersten nette befehl kommt der Swap-befehl. Er kann auf die Adress und
  14. Datenregister zugreifen, und vertauscht oberes Wort mit dem unteren.
  15. Aus...
  16.  
  17. $40981546
  18.  
  19. wird...
  20.  
  21. $15464098
  22.  
  23. Naja, hoert sich ja nicht besonders an. Aber den grund warum ich den Befehl
  24. vorstelle, ich hatte ja gesagt ich stelle nur die Befehle vor die man
  25. wirklich zum Intro schreiben braucht, ist, das er sich ganz besonders gut
  26. fuer manipulationen an Copperlisten eignet, wenn es darum geht Adressen
  27. einzutragen.
  28. Wie ihr wisst sind die Adresse in einer Copperliste immer getrennt in
  29. Highwort und Lowwort.
  30.  
  31. Um die adresse $40000 als adresse fuer die erste Bitplane festzulegen, muss
  32. man das ja die beiden befehle..
  33.  
  34. $00e0 $0004
  35. $00e2 $0000
  36.  
  37. schreiben. Naja wenn wir wissen wo das liegt koennen wir das ja relativ
  38. einfach eintragen. Aber was ist wenn wir zum Beispiel die Adresse der
  39. Sprite datenliste in die Copperliste eintragen wollen. Dann gibt es schon
  40. schwierigkeiten. Wir koennten das zwar ermitteln, weil wir ja das mainprog
  41. mit Org/Load fixieren. Aber die Adresse der Datenliste aendert sich ja
  42. jedesmal wenn wir erweiterungen am listing vornehmen, also das ist es nicht.
  43. Die moeglichkeit ist also, sich mit Move.l # die Adresse in ein Datenregister
  44. zu holen, um dann die Zwei worte in die Copperliste einzutragen.
  45. In der Praxis sieht das dann so aus...
  46.  
  47.         Move.l  #Sprite1,d0
  48.         Move.w  d0,Copperlist+2
  49.         Swap    d0
  50.         Move.w  d0,Copperlist+6
  51.         Rts
  52.  
  53. Copperlist:
  54. dc.w    $0120,$0000
  55. dc.w    $0122,$0000
  56. dc.l    $-2
  57.  
  58. Sprite1:
  59. ..Hier liegt dann die Spritedefinition
  60.  
  61. Die Funktion muesste eigentlich Klar sein...
  62.  
  63. Dann kommt ein Kuerzel das man z.b hinter die Befehle Move, Add und Sub
  64. klemmen kann.
  65.  
  66. Naemlich `q`...
  67.  
  68. Es bedeutet dann soviel wie Quick, man kann damit allerdings nur
  69. vorzeichenbehaftete 4 bit werte uebertragen. Also von -8 bis +7.
  70. Quick wird es genannt weil es sehr schnell geht, denn der wert wird direkt
  71. in den Befehl mit eingebaut. Es kommt nur ein Wort bei raus, und das der
  72. Prozessor das Schneller abarbeiten kann ist ja wohl jedem Klar..ne.
  73.  
  74. Wenn irgendwie moeglich solltet ihr wenn irgendwie moeglich bei Sprung
  75. operationen immer die Branch befehle vor ziehen. Also anstatt
  76.  
  77. Jmp und Jsr...immer Bra und Bsr...
  78.  
  79. Denn dort ist sowieso der Befehl kuerzer. Man kann ihn aber auch von hand
  80. noch kuerzer machen. Indem man einfach .S fuer kurze Distanz, oder .L fuer
  81. lange Distanz eingebt. Wenn ihr euch vertut und Kurz statt lang eingebt ist
  82. das nicht so schlimm, der Seka merkt das und verbessert euch. Falls aber
  83. umgekehrt, wenn ihr also .L schreibt, aber .S moeglich waere, tja dann habt
  84. ihr pech gehabt, da mischt sich der Seka nicht ein.
  85. Dieses Kuerzel habt ihr aber auch schon in meinen Listings gesehen. Es
  86. klebt immer an den Bne`s, Beq`s, und an den Bsr`s dran. Naja jetzt wisst
  87. ihr auch was das bedeutet.
  88.  
  89. Eine weiteres Kuerzel kann man noch in den Daten fuer den befehl
  90. unterbringen. Und zwar wenn man mit Adresse arbeitet die eigentlich nur ein
  91. Wort lang sind, dann waere es unsinnig ein ganzes langwort dafuer zu
  92. verschwenden. Es koennte dann so aussehen...
  93.  
  94. Vorher
  95.         Move.l $00000040,$00000050
  96.  
  97. schiebt das langwort von $40 nach $50
  98. Das ergibt nach dem Assemblieren
  99.  
  100. 2 Bytes fuer den Move befehl
  101. 4 Bytes fuer die Adresse $00000040
  102. 4 Bytes fuer die Adresse $00000050
  103.  
  104. ----------------------------------
  105. 10 Bytes
  106.  
  107. Wenn ihr aber die Kuerzel benutzt, sieht es so aus.
  108.  
  109.         Move.l $0040.w,$0050.w
  110.  
  111. belegt..
  112.  
  113. 2 Bytes fuer den Move befehl
  114. 2 Bytes fuer die Adresse $00000040
  115. 2 Bytes fuer die Adresse $00000050
  116.  
  117. ----------------------------------
  118. 6 Bytes
  119.  
  120. Denkt daran, die schreibweise $0040 aendert nichts, das .w muss dahinter,
  121. denn ich kann den Befehl mit den Langwoertern auch so schreiben.
  122.  
  123.         Move.l $40,$50
  124.  
  125. Es bleiben langwoerter, und als solche werden sie eingesetzt.
  126.  
  127. Naja, wir haben also im Beispiel 4 Bytes gespart, was das ist nicht viel,
  128. das meint ihr aber auch nur, wenn ihr mal euren ersten Bootblock
  129. beschreibt, dann werdet ihr noch an mich denken, den dort zaehlt jedes
  130. Byte.
  131. Leider gibt es kein Kuerzel .B, denn dann waere die ersparnis noch
  132. groesser.
  133.  
  134. Jetzt kommt ein Befehl den ich manchmal benutze, um schnell irgend was
  135. auszutauschen.
  136. Stellt euch vor ihr habt irgendwann mal eine tolle Routine geschrieben, die
  137. einen Haufen sachen ausrechnet, und die ergebnisse in allen Datenregistern,
  138. das heisst von 0 bis 7. Und irgendwann schreibt ihr mal ein programm das
  139. halt solche werte braucht, und ihr erinnert euch an die alte
  140. Routine...Jetzt merkt ihr aber das die routine etwas anders ist, und zwar
  141. so das das Ergebnis was die neue Routinen in d6 braucht, in d7 liegt, und
  142. das ergebnis was sie in d7 braucht, aber in d6 liegt.
  143. Jetzt gibt es drei moeglichkeiten dieser Situation Herr zu werden.
  144.  
  145. Wir schreiben eine der beiden Routinen um...was aber bei 20 Kilobyte
  146. SourceCode nicht gerade leicht ist. Und da Programmierer grundsaetzlich
  147. faule Menschen sind, faellt das also weg.
  148.  
  149. Also muessen wir gucken wie wir da sachen vertauscht kriegen, so viel ist
  150. klar. Man kann es mit dem Stack, oder mit einer X-beliebigen adresse
  151. machen. Hier die zwei moeglichkeiten.
  152.  
  153.         Move.l d6,$40000
  154.         Move.l d7,d6
  155.         Move.l $40000,d7
  156.  
  157. Oder
  158.  
  159.         Move.l  d6,-(a7)
  160.         Move.l  d7,d6
  161.         Move.l  (a7)+,d7
  162.  
  163. Die zweite moeglichkeit ist etwas komplizierter, aber wird im Source
  164. kuerzer als die erste. Der effekt ist derselbe, was vorher in d6 stand
  165. steht jetzt in d7, und umgekehrt.
  166.  
  167. Aber jetzt tritt der neue Befehl auf die Buehne. Er heisst schlicht und
  168. ergreifend `Exchange` kurz `EXG`, und mit ihm passiert dann die ganze
  169. sachen in einem Wort.
  170.  
  171.         Exg     d6,d7
  172.  
  173. Das wars...Im prinzip ist es dasselbe wie die kuerzere Variante von eben,
  174. denn der Prozessor macht genau das auch. Nur wenn er es macht geht es
  175. natuerlich viel schneller. Alles Klor ?
  176.  
  177. Es kommt immer mal wieder vor das man, wenn man ein Intro programmiert, die
  178. einzelnen Effekte in Modulen abarbeiten laesst. Dabei kann es vorkommen das
  179. man die module an verschiedenen Tagen programmiert, und nicht darauf achtet
  180. welche Arbeits und datenregister man den nun noch frei hat. Und wenn man
  181. ein Intro mit 20 Effektmodulen hat, dann wird es eng mit den registern, mit
  182. denen man doch so hervorragend arbeiten kann, oder.
  183.  
  184. So, da gibt es eine ganz einfache sache. Wir legen uns jeden die inhalte der
  185. Datenregister und der Adressregister jedes Modules, einen Sicherungsplatz
  186. an, indem wir nach abarbeitung des Modul alle sachen abspeichern, und bevor
  187. wir das naechste mal mit dem modul anfangen, holen wir uns einfach die
  188. sachen wieder rein. Das saehe, wenn wir es jetzt machen muessten allerdings
  189. etwas lang, naemlich so aus.
  190.  
  191.         Move.l d0,$40000
  192.         Move.l d1,$40004
  193.         ....
  194.         ....
  195.         Move.l a0,$40020
  196.         Move.l a1,$40024
  197.  
  198. naja das waere ja ein bisschen lang. Das haben sich die Leute die den 68000
  199. gebaut haben auch gedacht, und deshalb fuer den move befehl noch ein Kurzel
  200. ausgedacht. naemlich `m`. Das `m` steht fuer viele oder mehrere, das heisst
  201. wir koennen mit einem Befehl direkt mehrere register retten. Wir koennen
  202. sie dann auf den Stack oder einfach in den Speicher schreiben. Der Befehl
  203. der den Kompletten registerinhalt nach $40000 rettet sehae dann so aus.
  204.  
  205.         Movem.l d0-d7/a0-a6,$40000
  206.  
  207. Er erhoeht auch selbsttaetig die adresse wo er das hinschreibt.
  208. Wir muessen allerdings nicht alles retten, sondern wir koennen auch ganz
  209. bestimmt retten. Wenn wir nur d0,d1,d4,d5,d7,a0,a1,a2 und a6 retten wollen
  210. schreiben wir einfach
  211.  
  212.         Movem.l d0-d1/d4-d5/d7/a0-a2/a6,$40000
  213.  
  214. Also ihr seht..ziemlich cool der Befehl. Natuerlich geht es zurueck
  215. genauso. Der Befehl der den ersten Movem befehl von mir rueckgaengig macht
  216. heisst
  217.  
  218.         Movem.l $40000,d0-d7/a0-a6
  219.  
  220. Mehr nicht...
  221.  
  222. Nach moeglichkeit den Clr befehl in langen schleifen und auch sonst meiden.
  223. Denn er dauert einfach zu lange. Ein Ersatz fuer diese Schleife
  224.  
  225.         Lea $40000,a0
  226.         Move.w #$ffff,d0
  227. Clearloop:
  228.         Clr.l (a0)+
  229.         Dbf d0,clearloop
  230.         Rts
  231.  
  232. waere ohne Clr.l, und sehr viel schneller...
  233.  
  234.         Lea $40000,a0
  235.         Move.l #$ffff,d0
  236. Clearloop:
  237.         Moveq.l #0,(a0)+
  238.         Dbf d0,clearloop
  239.         Rts
  240.  
  241. All right ?
  242.  
  243. Wenn ihr mal etwas groessere sachen programmiert, und ihr kleine Zeitliche
  244. abstaende braucht, dann koennt ihr euch ja mit der einfachen Warteschleife
  245. helfen die ihr schon kennt. Aber gerade bei sachen in Echtzeit, muss man
  246. manchmal kurze abstaende warten. Je nach dem sind die Abstaende sogar so
  247. kurz, das man noch nicht mal eine kleine Routine dazwischensetzen kann.
  248. Dazu gibt es einen netten Befehl, der eigentlich nichts macht. Und so
  249. heisst er auch..
  250.  
  251.         `Nop` - No OPeration
  252.  
  253. Der Prozessor braucht Vier Taktzyklen um zu merken das der Befehl garkeinen
  254. gueltigen Code ergibt, dann springt er weiter. Solche Codes gibt es noch
  255. viele andere. Die Erbauer von Prozessoren, nehmen immer einen davon der
  256. dann den Namen `Nop` kriegt, und dann ist das so.
  257.  
  258. So jetzt kommt die Aufstellung der Sprungkriterien fuer die Befehle aus der
  259. Gruppe der Bedingten Branch Befehle. Zwei davon kennt ihr ja schon, Bne und
  260. Beq, ich zaehle sie aber der komplettheit wegen nochmal auf.
  261.  
  262. Das B davor muesst ihr euch immer denken, da ich nur die bedingung
  263. beschreibe.
  264.  
  265. CC = Carry Flag nicht gesetzt           (Carry Flag wird spaeter erklaert)
  266.  
  267. CS = Carry Flag gesetzt
  268.  
  269. EQ = Zero Flag gesetzt, oder letzte Operation gleich 0
  270.  
  271. GE = Groesser oder Gleich    > =
  272.  
  273. GT = Groesser, aber mit vorzeichen    >
  274.  
  275. HI = Groesser    >
  276.  
  277. LE = Kleiner oder 0, aber mit vorzeichen    <
  278.  
  279. LS = Kleiner oder Gleich    < =
  280.  
  281. LT = Kleiner, aber mit vorzeichen    <
  282.  
  283. MI = Wert im Minus Bereich    -
  284.  
  285. NE = Zero Flag nicht gesetzt, oder letzte operation nicht 0    <>
  286.  
  287. PL = Wert im Plus Bereich
  288.  
  289. VC = Overflow nicht gesetzt, mit vorzeichen      (Overflow Flag kommt spaeter)
  290.  
  291. VS = Overflow gesetzt, mit vorzeichen
  292.  
  293.  
  294. So das waeren sie, den Groessten teil braucht man halt sehr selten, es ist
  295. aber schon mal gut wenn man weiss das es sie ueberhaupt gibt.
  296.  
  297. So jetzt noch ein Paar Klaerende worte zum Carry- und Overflow Flag.
  298.  
  299. Zuerst da carryflag....
  300.  
  301. Was die Flags sind wisst ihr ja schon, deshalb kann ich ja loslegen.
  302. Das Carry Flag ist praktisch das 33 ste Bit der Datenregister, wenn ein
  303. Wert durch Addition zu gross fuer ein Datenregister wird, dann wird der
  304. rest ins Carry geschrieben. Deshalb mus man es bei Addtion und Subtraktion
  305. immer beruecksichtigen.
  306.  
  307. Das Overflowflag ist immer dann gesetzt wenn bei der letzten operation, ein
  308. bereich ueberschritten wurde, sei es der Byte, Wort oder Langwort bereich.
  309. Sobald die Zahl diesen Ueberlaueft wird es gesetzt. Wofuer das gut sein
  310. soll weiss ich zwar nicht, aber ich habe es so gelernt.
  311.  
  312. So jetzt erstmal in die Heia, muss morgen inne Schule...
  313.  
  314. bis denne
  315.  
  316.                 Jeff Kandle
  317.